<?php

/**
 * mForge Framework
 *
 * LICENSE:
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * The license is bundled with this package in the file LICENSE.txt.
 * You may also obtain a copy of the License at this URL:
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * @copyright  Copyright (c) 2011, Jonathan Hedrén
 * @author     Jonathan Hedrén <jonathan.hedren@gmail.com>
 * @license    http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
 */

namespace mForge\Modules\Users;

use mForge\IDependent;
use mForge\IModule;
use mForge\Application;
use mForge\Events;
use mForge\Menu;
use mForge\RedirectResult;
use mForge\Request;
use mForge\Response;
use mForge\ValidationResult;
use mForge\ViewResult;
use mForge\Helpers\FlashMessenger;

use mForge\Modules\Menu\Module as MenuModule;

require_once 'lib/UserModel.php';
require_once 'lib/UserService.php';

class Module implements IModule, IDependent
{
    /**
     *
     * @var \mForge\Modules\FlashMessenger\Messenger
     */
    private $flashMessenger;

    /**
     *
     * @var \mForge\Modules\Menu\Module
     */
    private $menuModule;

    /**
     *
     * @var \mForge\Modules\Database\Module
     */
    private $persistenceModule;

    /**
     *
     * @var UserService
     */
    private $userService;

    /**
     *
     * @return array
     */
    public static function getDependencies()
    {
        return array(
            'Menu',
            'FlashMessenger',
            'Persistence'
        );
    }

    /**
     *
     * @param Application $app
     */
    public function init(Request $request, Response $response, Application $app, array $moduleConfig)
    {
        $this->userService = $userService = new UserService($this->persistenceModule->getDatabase(), $moduleConfig['userTable'], $moduleConfig['passwordHashAlgo'], $moduleConfig['passwordSalt']);

        // If the administration module is loaded, add a menu item to it
        $admininstrationMenu = $this->menuModule->getMenu('administration');
        if ($admininstrationMenu != null) {
            $usersMenuItem = new \mForge\Modules\Menu\MenuItem('users', 'users', 'Users', 0);
            $admininstrationMenu->addMenuItem($usersMenuItem);
        }
        
        $this->registerRoutes($app, $userService);
    }

    /**
     *
     * @return UserService
     */
    public function getUserService()
    {
        return $this->userService;
    }

    /**
     *
     */
    protected function registerRoutes($app, $userService)
    {
        $flashMessenger = $this->flashMessenger;

        /**
         * List users
         */
        $app->route('users', function() use ($userService) {
            return new ViewResult(array(
                'pageTitle' => 'Users',
                'users' => $userService->findAll()
            ), 'list');
        });

        /**
         * Create user
         */
        $app->route('users/create', function(UserModel $model) {
            return new ViewResult(array(
                'pageTitle' => 'Create user',
                'userModel' => $model
            ), 'edit');
        });

        /**
         * Create user post
         */
        $app->route(
            'users/create',
            'post',
            function(UserModel $model, ValidationResult $validationResult) use ($userService, $flashMessenger) {
                if ($validationResult->isValid()) {
                    
                    $model->createdDate = date('Y-m-d H:i:s');
                    $model->password = $userService->generatePasswordHash($model->password);
                    $model->failedLoginAttempts = 0;
                    
                    $userService->save($model);

                    $flashMessenger->addMessage('User created.');
                    
                    return new RedirectResult('users');
                }
                return new ViewResult(array(
                    'pageTitle' => 'Create user',
                    'userModel' => $model
                ), 'edit');
            }
        );


        /**
         * Edit user
         */
        $app->route('users/edit/@id', function($id, UserModel $model) use ($userService) {
            $model = $userService->findById($id);
            if ($model == null) {
                return new RedirectResult('users');
            }

            return new ViewResult(array(
                'pageTitle' => 'Edit user',
                'userModel' => $model
            ), 'edit');
        });

        /**
         * Edit user post
         */
        $app->route(
            'users/edit/@id',
            'post',
            function($id, $clearLock, UserModel $model, ValidationResult $validationResult) use ($userService, $flashMessenger) {

                $persistentModel = $userService->findById($id);
                if ($persistentModel == null) {
                    return new RedirectResult('users');
                }

                if (empty($model->password)) {
                    $validationResult->setFieldValid('password');
                }
                
                if ($validationResult->isValid()) {
                    
                    if (empty($model->password)) {
                        $model->password = $persistentModel->password;
                    } else {
                        $model->password = $userService->generatePasswordHash($model->password);
                    }
                    
                    $model->createdDate = $persistentModel->createdDate;
                    $model->lastLoginDate = $persistentModel->lastLoginDate;
                    $model->failedLoginAttempts = $persistentModel->failedLoginAttempts;
                    $model->isLockedOut = $persistentModel->isLockedOut;

                    if ($clearLock) {
                        $model->failedLoginAttempts = 0;
                        $model->isLockedOut = false;
                    }
                    
                    $userService->save($model);
                    
                    $flashMessenger->addMessage('User saved.');
                    return new RedirectResult('users');
                }

                return new ViewResult(array(
                    'pageTitle' => 'Edit user',
                    'userModel' => $model
                ), 'edit');
            }
        );

        /**
         * Delete user
         */
        $app->route('users/delete/@id', function($id) use ($userService) {
            $model = $userService->findById($id);

            return new ViewResult(array(
               'pageTitle' => 'Delete user',
               'userModel' => $model
            ), 'delete');
        });

        /**
         * Delete user post
         */
        $app->route('users/delete/@id', 'post', function($id) use ($userService, $flashMessenger) {
            $model = $userService->findById($id);

            $userService->delete($model->id);
            $flashMessenger->addMessage('User deleted.');
            return new RedirectResult('users');
        });
    }

    /**
     *
     * @param \mForge\Modules\FlashMessenger\Module $flashMessengerModule
     */
    public function setFlashMessengerModule(IModule $flashMessengerModule)
    {
        $this->flashMessenger = $flashMessengerModule->getMessenger();
    }


    /**
     *
     * @param IModule $menuModule
     */
    public function setMenuModule(IModule $menuModule)
    {
        $this->menuModule = $menuModule;
    }

    /**
     *
     * @param \mForge\Modules\Persistence\Module $persistenceModule
     */
    public function setPersistenceModule(IModule $persistenceModule)
    {
        $this->persistenceModule = $persistenceModule;
    }
}